home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
clang
/
nn.zip
/
DECODE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-31
|
7KB
|
368 lines
/*
* Decode one or more uuencoded article back to binary form.
*
* UNIX/NN VERSION
* This version cannot be used as a stand-alone uud!
* This version is made: 16 June 1989.
*
* From the Berkeley original, modified by MSD, RDR, JPHD & WLS.
*/
#include "config.h"
export char *decode_header_file = "Decode.Headers";
#define MAXCHAR 256
#define LINELEN 256
#define NORMLEN 60 /* allows for 80 encoded chars per line */
#define SEQMAX 'z'
#define SEQMIN 'a'
static char seqc;
static int first, secnd, check, numl;
static FILE *out;
static char *target;
static char blank;
static int chtbl[MAXCHAR], cdlen[NORMLEN + 3];
static char ofname[FILENAME];
static int state;
#define NO_ADVANCE 0x10
#define FIND_BEGIN 0x01
#define FIND_BEGIN_AFTER_ERROR 0x02
#define DECODE_TEXT 0x03
#define SKIP_TRAILING (0x04 | NO_ADVANCE)
#define SKIP_LEADING 0x05
#define FOUND_END (0x06 | NO_ADVANCE)
#define DECODE_ERROR (0x07 | NO_ADVANCE)
#define OTHER_ERROR (0x08 | NO_ADVANCE)
#define NEW_BEGIN (0x09 | NO_ADVANCE)
uud_start(dir)
char *dir;
{
target = dir;
out = NULL;
seqc = SEQMAX;
check = 1;
first = 1;
secnd = 0;
state = FIND_BEGIN;
}
uud_end()
{
if (out != NULL) {
fclose(out);
msg("%s INCOMPLETE -- removed", ofname);
unlink(ofname);
}
}
uudecode(ah, in)
register article_header *ah;
FILE *in;
{
int mode, onedone, lens;
char dest[FILENAME], buf[LINELEN];
numl = onedone = 0;
if (state == FIND_BEGIN)
inittbls();
/*
* search for header or translation table line.
*/
while ((state & NO_ADVANCE) ||
(ftell(in) < ah->lpos && fgets(buf, sizeof buf, in) != NULL)) {
numl++;
switch (state) {
case NEW_BEGIN:
if (out != NULL) {
msg("INCOMPLETE FILE: %s -- removed", ofname);
user_delay(5);
fclose(out);
out = NULL;
unlink(ofname);
}
/* fall thru */
case FIND_BEGIN:
case FIND_BEGIN_AFTER_ERROR:
if (strncmp(buf, "table", 5) == 0) {
gettable(in);
continue;
}
if (strncmp(buf, "begin", 5) == 0) {
lens = strlen(buf);
buf[--lens] = '\0';
if(sscanf(buf,"begin%o%s", &mode, dest) != 2)
continue;
if (target != NULL)
sprintf(ofname, "%s%s", target, dest);
else
strcpy(ofname, dest);
if ((out = open_file(ofname, OPEN_CREATE)) == NULL) {
msg("Cannot create file: %s\n", ofname);
goto err;
}
chmod(ofname, mode);
if (decode_header_file)
store_header(ah, in, target, decode_header_file);
msg("Decoding: %s", ofname);
state = DECODE_TEXT;
}
continue;
case SKIP_LEADING:
state = decode_line(buf);
continue;
case DECODE_TEXT:
state = decode_line(buf);
onedone = 1;
continue;
case FOUND_END:
fclose(out);
out = NULL;
state = FIND_BEGIN;
continue;
case SKIP_TRAILING:
state = SKIP_LEADING;
return 0;
case DECODE_ERROR:
state = SKIP_TRAILING;
continue;
case OTHER_ERROR:
fclose(out);
out = NULL;
state = FIND_BEGIN_AFTER_ERROR;
goto err;
}
}
if (onedone) {
if (state == DECODE_TEXT) state = SKIP_LEADING;
return 0;
}
if (state == FIND_BEGIN_AFTER_ERROR) return -1;
msg("No 'begin' line");
err:
user_delay(2);
return -1;
}
/*
* decode one line, write on out file
*/
static decode_line(buf)
char *buf;
{
char outl[LINELEN];
register char *bp, *ut;
register int *trtbl = chtbl;
register int n;
register int blen; /* binary length (from decoded file) */
register int rlen; /* calculated input line length */
register int len; /* actual input line length */
len = strlen(buf);
if (--len < 0) return state;
buf[len] = '\0';
/*
* Get the binary line length.
*/
if ((blen = trtbl[buf[0]]) < 0) {
if (state == SKIP_LEADING) {
if (strncmp(buf, "begin", 5) == 0)
return NEW_BEGIN;
return SKIP_LEADING;
}
/*
* end of uuencoded file ?
*/
if (strncmp(buf, "end", 3) == 0)
return FOUND_END;
/*
* end of current file ? : get next one.
*/
if (strncmp(buf, "include", 7) == 0) {
msg("Cannot handle 'include' lines -- unpack with uud");
return OTHER_ERROR;
}
/*
* trailing garbage
*/
return SKIP_TRAILING;
}
rlen = cdlen[blen];
if (len != rlen && state == SKIP_LEADING)
return SKIP_LEADING;
/*
* Is it the empty line before the end line ?
*/
if (blen == 0) return state;
/*
* Pad with blanks.
*/
for (bp = buf + len, n = rlen - len; --n >= 0; ) *bp++ = blank;
/*
* Verify
*/
for (n = rlen, bp = buf; --n >= 0; bp++)
if (trtbl[*bp] < 0) {
if (state == SKIP_LEADING) return SKIP_LEADING;
return DECODE_ERROR;
}
/*
* Check for uuencodes that append a 'z' to each line....
*/
if (check)
if (secnd) {
secnd = 0;
if (buf[rlen] == SEQMAX) check = 0;
} else if (first) {
first = 0;
secnd = 1;
if (buf[rlen] != SEQMAX) check = 0;
}
/*
* There we check.
*/
if (check) {
if (buf[rlen] != seqc) {
if (state == SKIP_LEADING) return SKIP_LEADING;
return DECODE_ERROR;
}
if (--seqc < SEQMIN) seqc = SEQMAX;
}
/*
* output a group of 3 bytes (4 input characters).
* the input chars are pointed to by p, they are to
* be output to file f. blen is used to tell us not to
* output all of them at the end of the file.
*/
ut = outl;
n = blen;
bp = &buf[1];
while (--n >= 0) {
*(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
if (n > 0) {
*(ut++) = (trtbl[bp[1]] << 4) | (trtbl[bp[2]] >> 2);
n--;
}
if (n > 0) {
*(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
n--;
}
bp += 4;
}
if (fwrite(outl, 1, blen, out) <= 0) {
msg("Error on writing decoded file");
return OTHER_ERROR;
}
return DECODE_TEXT;
}
/*
* Install the table in memory for later use.
*/
static inittbls()
{
register int i, j;
/*
* Set up the default translation table.
*/
for (i = 0; i < ' '; i++) chtbl[i] = -1;
for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
for (i = ' ' + 64; i < MAXCHAR; i++) chtbl[i] = -1;
chtbl['`'] = chtbl[' ']; /* common mutation */
chtbl['~'] = chtbl['^']; /* an other common mutation */
blank = ' ';
/*
* set up the line length table, to avoid computing lotsa * and / ...
*/
cdlen[0] = 1;
for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
}
static gettable(in)
FILE *in;
{
char buf[LINELEN];
register int c, n = 0;
register char *cpt;
for (c = 0; c <= MAXCHAR; c++) chtbl[c] = -1;
for (;;) {
if (fgets(buf, sizeof buf, in) == NULL) {
msg("EOF while in translation table.\n");
return -1;
}
numl++;
if (strncmp(buf, "begin", 5) == 0) {
msg("Incomplete translation table.\n");
return -1;
}
cpt = buf + strlen(buf) - 1;
*cpt = ' ';
while (*(cpt) == ' ') {
*cpt = 0;
cpt--;
}
cpt = buf;
while (c = *cpt) {
if (chtbl[c] != -1) {
msg("Duplicate char in translation table.\n");
return -1;
}
if (n == 0) blank = c;
chtbl[c] = n++;
if (n >= 64) return 0;
cpt++;
}
}
}